package com.example.docking.job;

import com.example.docking.controller.*;
import com.example.docking.dao.qingflow.Answer;
import com.example.docking.dao.qingflow.QingflowApplyResponse;
import com.example.docking.dao.qingflow.QingflowTokenResponse;
import com.google.gson.Gson;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
@EnableScheduling
public class JobTask {

    private static final Logger logger = LoggerFactory.getLogger(JobTask.class);

    private final SalesOrderController salesOrderController;
    private final InvPickController invPickController;
    private final XKYPurchaseOrderController xkyPurchaseOrderController;
    private final XKYChangeOrderController xkyChangeOrderController;
    private final XKYDJOrderController xkyDJOrderController;
    private final XKYInvoiceOrderController xkyInvoiceOrderController;
    private final ERPApCreditController erpApCreditController;
    private final ERPApPreCreditController erpApPreCreditController;
    private final ERPPurInboundController erpPurInboundController;
    private final ConfigurableApplicationContext context;

    @Value("${qingflow.wsId}")
    private String wsId;

    @Value("${qingflow.wsSecret}")
    private String wsSecret;

    @Value("${qingflow.applyId}")
    private String applyId;

    @Value("${qingflow.accessToken.url}")
    private String accessTokenUrl;

    @Value("${qingflow.apply.url}")
    private String applyUrl;

    @Value("${qingflow.timeout}")
    private int timeout;

    private final OkHttpClient httpClient;
    private final Gson gson;

    // 通过构造函数进行依赖注入
    @Autowired
    public JobTask(SalesOrderController salesOrderController,
                   InvPickController invPickController,
                   XKYPurchaseOrderController xkyPurchaseOrderController,
                   XKYChangeOrderController xkyChangeOrderController,
                   XKYDJOrderController xkyDJOrderController,
                   XKYInvoiceOrderController xkyInvoiceOrderController,
                   ERPApCreditController erpApCreditController,
                   ERPApPreCreditController erpApPreCreditController,
                   ERPPurInboundController erpPurInboundController,
                   ConfigurableApplicationContext context) {
        this.salesOrderController = salesOrderController;
        this.invPickController = invPickController;
        this.xkyPurchaseOrderController = xkyPurchaseOrderController;
        this.xkyChangeOrderController = xkyChangeOrderController;
        this.xkyDJOrderController = xkyDJOrderController;
        this.xkyInvoiceOrderController = xkyInvoiceOrderController;
        this.erpApCreditController = erpApCreditController;
        this.erpApPreCreditController = erpApPreCreditController;
        this.erpPurInboundController = erpPurInboundController;
        this.context = context;
        this.gson = new Gson();
        this.httpClient = new OkHttpClient.Builder()
                .connectTimeout(timeout, TimeUnit.MILLISECONDS)
                .readTimeout(timeout, TimeUnit.MILLISECONDS)
                .writeTimeout(timeout, TimeUnit.MILLISECONDS)
                .build();
    }

    // 监控销售订单
    @Scheduled(cron = "0 0/1 * * * ?")
    public void monitorSalesOrder() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            synchronized (this) {
                System.out.println("监控销售订单Monitoring Sales Order");
                salesOrderController.insertRaskGetBySalesOrder();
            }
        } finally {
            MDC.clear();
        }
    }

    // 监控生产任务单
    @Scheduled(cron = "30 0/3 * * * ?")
    public void monitorProductionTask() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            synchronized (this) {
                System.out.println("监控生产任务单Monitoring Production Task");
                salesOrderController.putJXRaskOrder();
            }
        } finally {
            MDC.clear();
        }
    }

    // 监控生产领料单
    @Scheduled(cron = "0 0/1 * * * ?")
    public void monitorInvPick() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            synchronized (this) {
                System.out.println("监控生产领料Monitoring InvPick");
                invPickController.SelectInvPick();
            }
        } finally {
            MDC.clear();
        }
    }

    // 监控携客云采购订单
    @Scheduled(cron = "0 0/1 * * * ?")
    public void monitorXKYPurchaseOrder() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            synchronized (this) {
                System.out.println("监控携客云采购订单");
                xkyPurchaseOrderController.selectPurchaseOrder();
            }
        } finally {
            MDC.clear();
        }
    }

    // 监控携客云采购变更单
    @Scheduled(cron = "10 0/5 * * * ?")
    public void monitorXKYChangeOrder() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            synchronized (this) {
                System.out.println("监控携客云采购变更单");
                xkyChangeOrderController.selectChangeOrder();
            }
        } finally {
            MDC.clear();
        }
    }

    // 监控携客云采购答交单
    @Scheduled(cron = "20 0/5 * * * ?")
    public void monitorXKYDJOrder() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            synchronized (this) {
                System.out.println("监控携客云采购答交单");
                xkyDJOrderController.selectDJOrder();
            }
        } finally {
            MDC.clear();
        }
    }

    // 监控ERP采购入库
    @Scheduled(cron = "0 0/1 * * * ?")
    public void monitorERPPurInbound() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            synchronized (this) {
                System.out.println("监控ERP采购入库");
                erpPurInboundController.selectPurInbound();
            }
        } finally {
            MDC.clear();
        }
    }

    // 监控携客云采购发票单
    @Scheduled(cron = "0 0/1 * * * ?")
    public void monitorXKYInvoiceOrder() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            synchronized (this) {
                System.out.println("监控携客云采购发票单");
                xkyInvoiceOrderController.selectInvoiceOrder();
            }
        } finally {
            MDC.clear();
        }
    }

    // 监控ERP预付款单
    @Scheduled(cron = "0 0/1 * * * ?")
    public void monitorERPApPreCredit() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            synchronized (this) {
                System.out.println("监控ERP预付款单");
                erpApPreCreditController.selectApPreCredit();
            }
        } finally {
            MDC.clear();
        }
    }

    // 监控ERP付款单
    @Scheduled(cron = "0 0/1 * * * ?")
    public void monitorERPApCredit() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            synchronized (this) {
                System.out.println("监控ERP付款单");
                erpApCreditController.selectApCredit();
            }
        } finally {
            MDC.clear();
        }
    }

    // 监控轻流开关状态
    @Scheduled(cron = "0 0/1 * * * ?")
    public void monitorQingflowSwitch() {
        MDC.put("requestId", UUID.randomUUID().toString());
        try {
            logger.info("开始监控轻流开关状态...");
            monitorSystemSwitchStatus();
        } catch (Exception e) {
            logger.error("监控轻流开关状态失败", e);
        } finally {
            MDC.clear();
        }
    }

    private void monitorSystemSwitchStatus() throws IOException {
        // 第一步：获取accessToken
        String accessToken = getAccessToken();
        if (accessToken == null) {
            logger.warn("获取accessToken失败，跳过本次检查");
            return;
        }

        // 第二步：调用应用详情接口
        String switchStatus = getSwitchStatus(accessToken);
        if (switchStatus == null) {
            logger.warn("获取开关状态失败，跳过本次检查");
            return;
        }

        // 第三步：检查开关状态
        logger.info("当前系统开关状态：{}", switchStatus);
        if ("关".equals(switchStatus)) {
            logger.error("检测到系统开关为'关'，即将关闭应用...");
            // 等待一小段时间确保日志写入完成
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            context.close();
        }
    }

    private String getAccessToken() throws IOException {
        String url = accessTokenUrl + "?wsId=" + wsId + "&wsSecret=" + wsSecret;

        Request request = new Request.Builder()
                .url(url)
                .build();

        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                logger.error("获取accessToken失败，HTTP状态码：{}", response.code());
                return null;
            }

            String responseBody = response.body().string();
            QingflowTokenResponse tokenResponse = gson.fromJson(responseBody, QingflowTokenResponse.class);

            if (tokenResponse.getErrCode() != 0) {
                logger.error("获取accessToken失败，错误码：{}，错误信息：{}", tokenResponse.getErrCode(), tokenResponse.getErrMsg());
                return null;
            }

            if (tokenResponse.getResult() == null) {
                logger.error("获取accessToken失败，结果为空");
                return null;
            }

            logger.debug("获取accessToken成功，过期时间：{}秒", tokenResponse.getResult().getExpireTime());
            return tokenResponse.getResult().getAccessToken();
        }
    }

    private String getSwitchStatus(String accessToken) throws IOException {
        String url = applyUrl + applyId;

        Request request = new Request.Builder()
                .url(url)
                .addHeader("accessToken", accessToken)
                .build();

        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                logger.error("获取应用详情失败，HTTP状态码：{}", response.code());
                return null;
            }

            String responseBody = response.body().string();
            QingflowApplyResponse applyResponse = gson.fromJson(responseBody, QingflowApplyResponse.class);

            if (applyResponse.getErrCode() != 0) {
                logger.error("获取应用详情失败，错误码：{}，错误信息：{}", applyResponse.getErrCode(), applyResponse.getErrMsg());
                return null;
            }

            if (applyResponse.getResult() == null || applyResponse.getResult().getAnswers() == null) {
                logger.error("获取应用详情失败，结果或答案列表为空");
                return null;
            }

            // 查找queId为412278468的答案（系统开关）
            for (Answer answer : applyResponse.getResult().getAnswers()) {
                if (412278468L == answer.getQueId() && answer.getValues() != null && !answer.getValues().isEmpty()) {
                    return answer.getValues().get(0).getValue();
                }
            }

            logger.warn("未找到queId为412278468的系统开关字段");
            return null;
        }
    }
}